﻿using System.Collections.Generic;
using System.IO;
using System.Linq;
using SCore.Util;
using UnityEditor;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.Settings;
using UnityEngine;
using UnityEngine.AddressableAssets;

namespace SCore.Editor.BuildPackage.Addressable
{
    public partial class BuildAddressable
    {
        public static readonly string Caching = "BundleCacheList";
        private static readonly string _verFileName = "AssetsVersion.txt";

        // 通关是否存在改文件 检查是否已经打过首包
        public static readonly string BuildContentSignPath =
            Application.streamingAssetsPath + "/BuildContentSignPath.txt";

        //重定向功能
        private static void BuildInternalIdTransformFuncCache(AddressableAssetBuildResult result)
        {
            var remoteBuildPath = BuildAddressable.GetAASRemoteBuildDir();
            var allBundles = new List<string>();
            var filePathList = result.FileRegistry.GetFilePaths().Where(s => s.EndsWith(".bundle"));
            foreach (var filePath in filePathList)
            {
                var bundlePath = filePath.Substring(remoteBuildPath.Length + 1);
                allBundles.Add(bundlePath);
            }

            //写入 重定向资源列表
            var json = JsonUtility.ToJson(new Serialization<string>(allBundles));
            var streamingAssetPath = $"{Application.streamingAssetsPath}/{Caching}";
            if (!Directory.Exists(streamingAssetPath))
            {
                Directory.CreateDirectory(streamingAssetPath);
            }

            File.WriteAllText($"{streamingAssetPath}/{Caching}.json", json);
        }


        #region BundleReport

        [System.Serializable]
        public class BundleInfo
        {
            public string _filePath;
            public string _internalBundleName;
            public string _sourceAssetGroup;
            public uint _crc;
            public string _hash;
            public string[] _assets;
            public string _size;
        }

        [System.Serializable]
        class BundleCollection
        {
            public List<BundleInfo> _bundles;
        }

        //导出日志分析
        private static void Build_ReportToBuildReport(AddressablesPlayerBuildResult result)
        {
            BundleCollection allBundles = new BundleCollection();
            allBundles._bundles = new List<BundleInfo>();
            foreach (var bundleBuildResult in result.AssetBundleBuildResults)
            {
                BundleInfo bundleInfo = new BundleInfo();
                bundleInfo._hash = bundleBuildResult.Hash;
                bundleInfo._filePath = bundleBuildResult.FilePath;
                bundleInfo._crc = bundleBuildResult.Crc;
                bundleInfo._internalBundleName = bundleBuildResult.InternalBundleName;
                bundleInfo._sourceAssetGroup = bundleBuildResult.SourceAssetGroup.Name;
                var bundle = AssetBundle.LoadFromFile(bundleInfo._filePath);
                bundleInfo._assets = bundle.GetAllAssetNames();
                FileInfo fileInfo = new FileInfo(bundleInfo._filePath);
                bundleInfo._size = fileInfo.Length.FormatFileSize();
                allBundles._bundles.Add(bundleInfo);
                bundle.Unload(true);
            }

            var json = JsonUtility.ToJson(allBundles, true);
            var reportPath = Application.dataPath.Replace("Assets", "Report");
            if (!Directory.Exists(reportPath))
                Directory.CreateDirectory(reportPath);
            File.WriteAllText(
                Application.dataPath.Replace("Assets",
                    $"Report/report_{BuildPipelineConfig.Instance._version}.txt"),
                json);
        }

        #endregion

        public static void Build_CopyBundleDirToAAS(AddressablesPlayerBuildResult result)
        {
            var remoteBuildPath = BuildAddressable.GetAASRemoteBuildDir();
            var aaDesDir = $"{Addressables.BuildPath}/{Caching}";
            if (Directory.Exists(aaDesDir)) Directory.Delete(aaDesDir, true);
            Directory.CreateDirectory(aaDesDir);
            var allSrcFile = Directory.EnumerateFiles(remoteBuildPath, "*.*", SearchOption.AllDirectories);
            foreach (var srcFile in allSrcFile)
            {
                var fileName = Path.GetFileName(srcFile);
                if (fileName != $"{Caching}.json")
                {
                    var destFile = $"{aaDesDir}/{fileName}";
                    File.Copy(srcFile, destFile);
                }
            }
        }

        public static void Build_CatalogToLoadPath(AddressablesPlayerBuildResult result)
        {
            var remoteBuildPath = BuildAddressable.GetAASRemoteBuildDir();
            var filePathList = result.FileRegistry.GetFilePaths().Where(
                (s) => { return s.Contains("catalog") && s.Contains(remoteBuildPath); }
            );
            string dirPath = remoteBuildPath.Replace("Bundle", "Catalog");
            if (Directory.Exists(dirPath))
            {
                Directory.Delete(dirPath, true);
            }

            Directory.CreateDirectory(dirPath);
            foreach (var file in filePathList)
            {
                File.Move(file, file.Replace("Bundle", "Catalog"));
            }
        }

        public static void BuildAddressableContentFinish(AddressablesPlayerBuildResult result)
        {
            Build_CopyBundleDirToAAS(result);
            BuildInternalIdTransformFuncCache(result);
            Build_CatalogToLoadPath(result);
            BuildAddressableFinish(result);
            Build_ReportToBuildReport(result);
            File.WriteAllText(BuildContentSignPath, "[Auto]:BuildAddressableContentFinish finish");
        }

        public static AddressablesPlayerBuildResult BuildAddressablesOverride(AddressableAssetSettings settings)
        {
            var result = new AddressablesPlayerBuildResult();
            result.Error = null;
            return result;
        }

        public static void BuildAddressableFinish(AddressablesPlayerBuildResult result)
        {
            //监听BuildAddressablePipline 构建完成
            var remoteBuildPath = BuildAddressable.GetAASRemoteBuildDir();
            remoteBuildPath = remoteBuildPath.Replace("Bundle", "");
            File.WriteAllText(remoteBuildPath + _verFileName, BuildPipelineConfig.Instance._version);

            // copy addressables_content_state.bin 到serverData，用于统一备份用
            var srcPath = ContentUpdateScript.GetContentStateDataPath(false);
            var destPath = remoteBuildPath + "addressables_content_state.bin.backup";
            // check destPath exists
            if (File.Exists(destPath))
            {
                File.Delete(destPath);
            }

            Debug.Log($"CopyFile: {srcPath} to {destPath}");
            FileUtil.CopyFileOrDirectory(srcPath, destPath);

            Debug.Log("[BuildPackage]:Build_Addressable End__________________");
        }


        public static void SBuild()
        {
            if (Application.isPlaying)
            {
                ($"[BuildPackage]:Build_Addressable failed, Application.isPlaying = true").Error();
                return;
            }

            "[BuildPackage]:Build_Addressable Start__________________".Log();
            string remotePath = BuildAddressable.GetAASRemoteBuildDir().Replace("/Bundle", "");
            if (Directory.Exists(remotePath))
            {
                Directory.Delete(remotePath, true);
            }

            if (File.Exists(BuildContentSignPath))
                BuildAddressable.BuildAddressableUpdate();
            else
                BuildAddressable.BuildAddressableContent();
        }
    }
}